package smetana.modules.ui.form.io;

import com.google.inject.Inject;
import org.apache.pivot.wtk.*;
import org.apache.pivot.wtkx.WTKX;
import smetana.modules.io.DbfImportService;
import smetana.modules.io.ProgressListener;
import smetana.modules.io.dbfimpot.ExternalModel;
import smetana.modules.ui.exceptions.WellKnownException;
import smetana.modules.ui.form.AbstractPanel;
import smetana.modules.ui.form.common.SelectFilePanel;
import smetana.modules.ui.listeners.ChangeListener;

import java.io.File;
import java.io.IOException;

/**
 * @author dmitry.mamonov
 */
public class ImportFromDbfPanel extends AbstractPanel {
    @WTKX
    TablePane.Row rowSelectFile;
    @WTKX
    PushButton buttonDoImport;
    @WTKX
    PushButton buttonCancel;
    @WTKX
    TextArea textReport;
    @WTKX
    Label labelStatus;

    @Inject
    DbfImportService dbfImportService;

    @Inject
    SelectFilePanel selectFilePanel;

    ExternalModel externalModel = null;

    Action actionDoImport = new Action(false) {
        @Override
        public void perform() {
            if (getExternalModel() != null) {
                tryStoreExternalData();
            } else {
                Alert.alert(MessageType.ERROR,
                        "Нет данных для импорта",
                        getComponent().getWindow());
            }

        }
    };


    Action actionCancel = new Action() {
        @Override
        public void perform() {

        }
    };

    @Override
    protected void init() {
        rowSelectFile.add(selectFilePanel.getComponent());
        buttonDoImport.setAction(actionDoImport);
        buttonCancel.setAction(actionCancel);
        selectFilePanel.getChangeListeners().add(new ChangeListener() {
            @Override
            public void onChange() {
                tryLoadDataFromDirectory(selectFilePanel.getFile());
            }
        });
        setExternalModel(null);
    }


    protected ExternalModel getExternalModel() {
        return externalModel;
    }

    protected void setExternalModel(ExternalModel externalModel) {
        this.externalModel = externalModel;
        actionDoImport.setEnabled(externalModel != null);


        if (externalModel != null) {
            textReport.setText(
                    String.format("Итоги по прочитанным данным:\n" +
                            "Контрагентов: ........ %5d\n" +
                            "Бригадиров: .......... %5d\n" +
                            "Документов: .......... %5d\n" +
                            "Позиций по документам: %5d\n" +
                            "\n" +
                            "Данные готовы к импорту,\n" +
                            "нажмите кнопку ИМПОРТ внизу формы что бы\n" +
                            "сохранить прочитанные данных в локальную базу данны.",
                            externalModel.listAgents().size(),
                            externalModel.listBrigaders().size(),
                            externalModel.listDocuments().size(),
                            externalModel.listDocumins().size()
                    ));
        } else {
            textReport.setText("Отчёт по импорту: <пусто>");
        }
    }

    protected void tryLoadDataFromDirectory(final File someFileInDirectory) {

        if (someFileInDirectory != null) {
            if (someFileInDirectory.exists() == true) {
                if (someFileInDirectory.isFile() == true) {
                    labelStatus.setText("Идёт чтение данных...");
                    new Thread("Loading data from DBF Files") {
                        @Override
                        public void run() {
                            setExternalModel(null);
                            try {
                                final ExternalModel loadedModel = dbfImportService.loadExternalModelFromDirectory(
                                        someFileInDirectory.getParentFile(),
                                        new ProgressListener() {
                                            @Override
                                            public void progress(final int value) {
                                                if (value % 100 == 0) {
                                                    ApplicationContext.queueCallback(new Runnable() {
                                                        @Override
                                                        public void run() {
                                                            labelStatus.setText("Прочитано " + value + " строк данных");
                                                        }
                                                    });
                                                }
                                            }
                                        });
                                ApplicationContext.queueCallback(new Runnable() {
                                    @Override
                                    public void run() {
                                        labelStatus.setText("Данные успешно прочитаны.");
                                        setExternalModel(loadedModel);
                                    }
                                });
                            } catch (final IOException e) {
                                labelStatus.setText("Ошибка при чтении данных");
                                ApplicationContext.queueCallback(new Runnable() {
                                    @Override
                                    public void run() {
                                        throw new WellKnownException("Не удалось прочитать данные из указанной директории: " +
                                                someFileInDirectory.getAbsolutePath() + ", возможно дикетроия содержит не верные либо " +
                                                "повреждённые данные.\n\n" +
                                                "Текст исходной ошибки: " + e.getMessage(),
                                                e);
                                    }
                                });
                            }

                        }
                    }.start();
                }
            }
        }
    }

    private void tryStoreExternalData() {
        final ExternalModel externalModelToStore = getExternalModel();
        setExternalModel(null);
        textReport.setText("Выполняется сохранение внешних данных в локальную базу данных:\n");
        new Thread("Storing data into database") {
            @Override
            public void run() {
                dbfImportService.storeExternalModel(externalModelToStore, new ProgressListener() {
                    @Override
                    public void progress(final int value) {
                        if (value % 100 == 0) {
                            ApplicationContext.queueCallback(new Runnable() {
                                @Override
                                public void run() {
                                    textReport.setText("В локальную базу импортировано " + value + " строк данных\n");
                                }
                            });
                        }
                    }
                });
                ApplicationContext.queueCallback(new Runnable() {
                    @Override
                    public void run() {
                        textReport.setText(textReport.getText() + "Данные загружены в локальную базу данных.");
                    }
                });
            }
        }.start();
    }

}
